package com.isae.chattingapp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Mode;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;

public class ListRosters extends Activity {

  public XMPPConnection RosterXmppConnection;
  public final static String USERNAME_EXTRA_INFO = "USERNAME";
  public final static String NAME_EXTRA_INFO = "NAME";
  
  ListView listview;
  Roster roster;
  
  private SharedPreferences sharedPref;
  
  private Context ListRostersContext;
  
  private AlertClass alert;
  private List<RosterInfo> ListRoster;
  
  private String CurrentLayout;
  RosterInfoAdapter adapter;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    setContentView(R.layout.activity_roster);
    CurrentLayout = "activity_roster";
    
    ListRostersContext = this;
    
    alert = new AlertClass(this);
    
    RosterXmppConnection = XMPPLogic.getInstance().getConnection();
    	
    listview = (ListView) findViewById(R.id.rosterList);
    
    ListRoster = new ArrayList<RosterInfo>();
    
    roster = RosterXmppConnection.getRoster();
    roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
    
    adapter = new RosterInfoAdapter(this, ListRoster);
    
    Prepare();
  }

//----------------------------------------------------------------------------------------------------------
  
  private void Prepare(){
	  listview.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
			RosterInfo ri= (RosterInfo)parent.getAdapter().getItem(position);
			
			Intent i = new Intent(ListRostersContext, ChattingActivity.class);
			i.putExtra(USERNAME_EXTRA_INFO, ri.RosterUsername);
			i.putExtra(NAME_EXTRA_INFO, ri.RosterName);
	    	startActivity(i);
		}
	  });   
	  
	  addFriendRequestListener();
	  ListAllRosters();
	  
	    
	    // Set the status to available
      Presence presence = new Presence(Presence.Type.available);
      RosterXmppConnection.sendPacket(presence);
  }
  
  public static int retrieveState_mode(Mode userMode, boolean isOnline) {
      int userState = 0;
      /** 0 for offline, 1 for online, 2 for away,3 for busy*/
      if(userMode == Mode.dnd) {
          userState = 3;
      } else if (userMode == Mode.away || userMode == Mode.xa) {   
          userState = 2;
      } else if (isOnline) {
          userState = 1;
      }
      return userState;
}
  
  public void ListAllRosters(){
        
//	  setContentView(R.layout.activity_roster);
	  // we clear everything in case we need to add a roster. This way the rosters are refreshed
	  //everytime.
	  ListRoster.clear();
	  setRosterListAdapter();
	  
	  // Accepting all the "friend" request automatically
	  //referring to http://www.igniterealtime.org/builds/smack/docs/latest/documentation/roster.html
	  // "Adding Entries to the Roster" paragraph
//	  roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
	  
      Collection<RosterEntry> entries = roster.getEntries();
      for (RosterEntry entry : entries) {

        Log.d("XMPPChatDemoActivity",  "--------------------------------------");
        Log.d("XMPPChatDemoActivity", "RosterEntry " + entry);
        Log.d("XMPPChatDemoActivity", "User: " + entry.getUser());
        Log.d("XMPPChatDemoActivity", "Name: " + entry.getName());
        Log.d("XMPPChatDemoActivity", "Status: " + entry.getStatus());
        Log.d("XMPPChatDemoActivity", "Type: " + entry.getType());
        Presence presence = roster.getPresence(entry.getUser());

        
        Log.d("XMPPChatDemoActivity", "Presence Status: "+ presence.getStatus());
        Log.d("XMPPChatDemoActivity", "Presence Type: " + presence.getType());
        
        if (! entry.getUser().toString().equalsIgnoreCase(RosterXmppConnection.getUser().substring(0, RosterXmppConnection.getUser().indexOf("@") ).toString()) ){
        	RosterInfo SingleRoster = new RosterInfo();
	        SingleRoster.RosterName = entry.getName().toUpperCase();
	        SingleRoster.RosterUsername = entry.getUser();
	        int state = retrieveState_mode(presence.getMode(),presence.isAvailable());
	        if (state == 0) {
	        	SingleRoster.RosterStatus = getString(R.string.Unavailable);
	        }else{
	        	SingleRoster.RosterStatus = getString(R.string.Available);
	        }
	        
	        ListRoster.add(SingleRoster);
        }
      }
      
      // changing layouts dynamically(switching from one xml to another)
      if (ListRoster.isEmpty()){
    	  if (!CurrentLayout.equals("no_roster_available")){
//    		  ViewGroup searchViewHolder = (ViewGroup)findViewById(R.id.NoRosterAvailableId);
//    		  View searchView = getLayoutInflater().inflate(R.id.NoRosterAvailableId, null);
//    		  searchViewHolder.addView(searchView);
    		  
    		  View CurrentView = (View) findViewById(R.id.ActivityRosterId);
	    	  CurrentLayout = "no_roster_available";
	    	  ViewGroup parent = (ViewGroup) CurrentView.getParent();
	    	  int index = parent.indexOfChild(CurrentView);
	    	  parent.removeView(CurrentView);
	    	  CurrentView = getLayoutInflater().inflate(R.layout.no_roster_available, parent, false);
	    	  parent.addView(CurrentView, index);
    	  }  
      }else{
    	  if (!CurrentLayout.equals("activity_roster")){
    		  View CurrentView = findViewById(R.id.NoRosterAvailableId);
	    	  CurrentLayout = "activity_roster";
	    	  ViewGroup parent = (ViewGroup) CurrentView.getParent();
	    	  int index = parent.indexOfChild(CurrentView);
	    	  parent.removeView(CurrentView);
	    	  CurrentView = getLayoutInflater().inflate(R.layout.activity_roster, parent, false);
	    	  parent.addView(CurrentView, index);
    	  }
    	  setRosterListAdapter();
      }
  }
  
 //////////////////////////////////////////////////////////////////////////////////////////////////
  private void addFriendRequestListener(){
	// Create a PacketFilter and add it to the listener(later on) so that the listener
	// will manage only the packet with subscribe, unsubscribe, subscribed, unsubscribed type
	  PacketFilter presenceFilter = new PacketFilter() {
			public boolean accept(Packet packet) {
				if (packet instanceof Presence) {
					Presence p = (Presence) packet;
					if(p.getType() == Presence.Type.subscribe 
							||p.getType() == Presence.Type.unsubscribe
							||p.getType() == Presence.Type.subscribed
							||p.getType() == Presence.Type.unsubscribed){
						return(true);
					}else{
						return(false);
					}
				}
				return (false);
			}
	  };
					
	  RosterXmppConnection.addPacketListener(new PacketListener() {
		  public void processPacket(Packet packet) {
			  	if (packet instanceof Presence) {
			  		final Presence presence = (Presence)packet;
			  		final String from = presence.getFrom();
			  	
				  	if (presence.getType() == Presence.Type.subscribe) {
				  		alert.builder.setTitle(getString(R.string.ChatRequest)+" "+from);
						alert.builder.setPositiveButton(getString(R.string.Add), new DialogInterface.OnClickListener() { 
						     @Override
						     public void onClick(DialogInterface dialog, int which) {
						    	 try {
									roster.createEntry(from, from, null);
								} catch (XMPPException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
					  				
				  				//CurrentUser sends SUBSCRIBE to the user who sent the request
				  				presence.setType(Presence.Type.subscribe);
				  				presence.setFrom(XMPPLogic.getInstance().getLoggedInUsername());
				  				presence.setTo(from);
				  				RosterXmppConnection.sendPacket(presence);
				  				
				  				//CurrentUser sends SUBSCRIBED to to the user who sent the request
				  				presence.setType(Presence.Type.subscribed);
				  				presence.setFrom(XMPPLogic.getInstance().getLoggedInUsername());
				  				presence.setTo(from);
				  				RosterXmppConnection.sendPacket(presence);
				  				
				  				ListAllRosters();
						     }
						});
						alert.builder.setNegativeButton(getString(R.string.Cancel), new DialogInterface.OnClickListener() {
					     @Override
					     public void onClick(DialogInterface dialog, int which) {
					    	//CurrentUser sends UNSUBSCRIBE to the user who sent the request
			  				presence.setType(Presence.Type.unsubscribe);
			  				presence.setFrom(XMPPLogic.getInstance().getLoggedInUsername());
			  				presence.setTo(from);
			  				RosterXmppConnection.sendPacket(presence);
			  				
				  			//CurrentUser sends UNSUBSCRIBED to the user who sent the request
			  				presence.setType(Presence.Type.unsubscribed);
			  				presence.setFrom(XMPPLogic.getInstance().getLoggedInUsername());
			  				presence.setTo(from);
			  				RosterXmppConnection.sendPacket(presence);
					     }
					 });
	
					 alert.builder.show();
			  	}
			}
		  }
	  }, presenceFilter);
  }
//////////////////////////////////////////////////////////////////////////////////////////////////
  private void setRosterListAdapter() {
	// Instead of using ArrayAdapter that can only displays strings, I created a UserInfo class
	  // that extends BaseAdapter. The advantage is that in this class i can display the objects that i want
	  // (ImageView, Buttons...)
	  
	  if(listview.getAdapter()== null){
		  listview.setAdapter(adapter);
	  }else{
		  adapter.notifyDataSetChanged();  
	  }
	  
	  
	  }
  
  @Override
  public boolean onPrepareOptionsMenu(Menu menu) {
	  menu.clear();
	  MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.sign_out, menu);
      return true;
  }
 
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
	  if (item.getItemId() == R.id.signout){
		  sharedPref = getSharedPreferences("CREDENTIALS",Context.MODE_PRIVATE);
			SharedPreferences.Editor editor = sharedPref.edit();
			editor.putString("username", null);
			editor.putString("password", null);
			editor.commit();
			
			// logging out
			Presence offlinePres = new Presence(Presence.Type.unavailable, "", 1, Presence.Mode.away);
			RosterXmppConnection.sendPacket(offlinePres);
	    	finish();
	  }else
		 if(item.getItemId() == R.id.addRoster){
			 alert.builder.setTitle(getString(R.string.EnterUserHint));

			 // Set up the input
			 final EditText input = new EditText(this);
			 // Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
			 input.setInputType(InputType.TYPE_CLASS_TEXT);
			 alert.builder.setView(input);

			 // Set up the buttons
			 alert.builder.setPositiveButton(getString(R.string.Add), new DialogInterface.OnClickListener() { 
			     @Override
			     public void onClick(DialogInterface dialog, int which) {
			         String user = input.getText().toString();
			  			try {
			  				roster.createEntry(user, user, null);
			  			} catch (XMPPException e1) {
			  				e1.printStackTrace();
			  			}
			  				
//		  				//current user sends SUBSCRIBE to user added
//		  				presence = new Presence(Presence.Type.subscribe);
//		  				presence.setFrom(XMPPLogic.getInstance().getLoggedInUsername());
//		  				presence.setTo(user);
//		  				RosterXmppConnection.sendPacket(presence);
//		  				
//		  				//current user sends SUBSCRIBED to to user added
//		  				presence = new Presence(Presence.Type.subscribed);
//		  				presence.setFrom(XMPPLogic.getInstance().getLoggedInUsername());
//		  				presence.setTo(user);
//		  				RosterXmppConnection.sendPacket(presence);
			  			
			  			ListAllRosters();
			     }
			 });
			 alert.builder.setNegativeButton(getString(R.string.Cancel), new DialogInterface.OnClickListener() {
			     @Override
			     public void onClick(DialogInterface dialog, int which) {
			    	 dialog.cancel();
			     }
			 });

			 alert.builder.show();
		 }
      return super.onOptionsItemSelected(item);
  }
  
  public void GetOutOfHere(String s){
	  alert.builder.setPositiveButton("OK", new DialogInterface.OnClickListener(){
          @Override
          public void onClick(DialogInterface dialog, int whichButton){
        	  RosterXmppConnection.disconnect();
  	    	  XMPPLogic.getInstance().setConnection(null);
        	  finish();
          }
      });
  	  alert.display_alert(s);
  }
}